package es

import (
	"context"
)

// Scroll
type Scroll struct {
	scrollId string
	item     chan interface{}
	Total    int64
	err      error
}

// Get next item from scroll
func (s *Scroll) Next() (item interface{}, err error) {
	return <-s.item, s.err
}

// 设置scroll存在时间, 默认5m (五分钟)
func (m *Model) ScrollAlive(alive string) *Model {
	m.query.scrollAlive = alive
	return m
}

// 设置scroll每次返回的结果数量, 默认1000
func (m *Model) ScrollSize(scrollSize int) *Model {
	m.query.scrollSize = scrollSize
	return m
}

// 获取scroll
func (m *Model) GetScroll() (*Scroll, error) {
	rawClient := m.client.rawClient
	scrollService := rawClient.Scroll(m.indexName...).Query(m.getBoolQuery()).Scroll(m.query.scrollAlive)
	//排序
	if m.query.sorters != nil && len(m.query.sorters) > 0 {
		scrollService.SortBy(m.query.sorters...)
	}
	ctx := context.Background()
	size := m.query.scrollSize
	r, err := scrollService.Size(size).Do(ctx)
	if err != nil {
		return nil, err
	}
	result, total, err := m.formatResult(r)
	if err != nil {
		return nil, err
	}
	scroll := &Scroll{
		scrollId: r.ScrollId,
		Total:    total,
		item:     make(chan interface{}, 0),
		err:      nil,
	}
	go m.scanScroll(scroll, result, size)
	return scroll, nil
}

// 循环获取scroll数据
func (m *Model) scanScroll(s *Scroll, result []interface{}, size int) {
	rawClient := m.client.rawClient
	for {
		if result == nil || len(result) == 0 {
			break
		}
		for _, item := range result {
			s.item <- item
		}
		ctx := context.Background()
		r, err := rawClient.Scroll().ScrollId(s.scrollId).Do(ctx)
		if err != nil {
			if err.Error() != "EOF" {
				s.err = err
			}
			break
		}
		result, s.Total, err = m.formatResult(r)
		if err != nil {
			s.err = err
			break
		}
	}
	ctx := context.Background()
	rawClient.Scroll().ScrollId(s.scrollId).Clear(ctx)
	close(s.item)
}
